# -*- coding: utf-8 -*-
# Copyright 2011-2012 MagiCycles.com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


import logging

from django.utils import simplejson
from django.http import HttpResponse

from oauth.utils import remove_oauth_params
from siteutils import escape_and_strip,escape_parameters

def returnjson(dit, default=None):
    resp = HttpResponse()
    resp.write(simplejson.dumps(dit, default=default))
    return resp

def returnjsoncallback(dit, callback, default=None):
    return HttpResponse('%s(%s)' % (callback,
                                    simplejson.dumps(dit, default=default)))

### functions ###
def get_methods(request):
    """return supported method list.
    Args: None
    Returns:
      methods: list(str), list of all supported methods.
    """
    result = {"status": "ok",
              "methods": APIRESTDispatcher.methods.keys(),
             }
    return result

def get_method_info(request, method_name):
    """return method's doc.
    Args:
        method_name: method name
    Returns:
        method_name: str, method name
        method_doc: str,  method's doc string"""
    result = {"status": "ok",
              "method_name": method_name,
              "method_doc": APIRESTDispatcher.get_method_doc(method_name),
             }
    return result


import routes_api
import oauth_api
import people_api
import gear_api
import stats_api

METHODS = {"get_methods": get_methods,
           "get_method_info": get_method_info,
           # routes and rides apis
           "create_route": routes_api.create_route,
           "remove_route": routes_api.remove_route,
           "get_route_by_id": routes_api.get_by_id,
           "get_routes_by_center": routes_api.get_routes_by_center,
           "get_routes_by_bounds": routes_api.get_routes_by_bounds,
           "get_routes_count_by_center": routes_api.get_routes_count_by_center,
           "get_routes_count_by_bounds": routes_api.get_routes_count_by_bounds,
           "get_all_routes": routes_api.get_all_routes,
           "get_routes_by_uid": routes_api.get_routes_by_uid,
           "get_directions_by_id": routes_api.get_directions_by_id,
           "get_comments_by_route_id": routes_api.get_comments_by_route_id,
           "add_comment": routes_api.add_comment,
           "save_comment_location": routes_api.save_comment_location,
           "get_rides_by_routeid": routes_api.get_rides_by_routeid,
           "get_rides_by_uid": routes_api.get_rides_by_uid,
           "get_ride_by_id": routes_api.get_ride_by_id,
           "get_all_rides": routes_api.get_all_rides,
           "search_routes": routes_api.search_routes,
           "search_comments": routes_api.search_comments,
           "log_a_ride": routes_api.log_a_ride,
           "update_ride_notes": routes_api.update_ride_notes,
           # people apis
           "get_rider_by_uid": people_api.get_rider_by_uid,
           "get_riders_by_bounds": people_api.get_riders_by_bounds,
           "get_riders_count_by_bounds": people_api.get_riders_count_by_bounds,
           "send_friend_request": people_api.send_friend_request,
           "confirm_friend_request": people_api.confirm_friend_request,
           "defriend": people_api.defriend,
           "add_favorite_route": people_api.add_favorite_route,
           "remove_favorite_route": people_api.remove_favorite_route,
           "unbind_outsite": people_api.unbind_outsite,
           "search_riders": people_api.search_riders,
           # gear apis
           "new_bike": gear_api.new_bike,
           "get_bike_by_id": gear_api.get_bike_by_id,
           "remove_bike": gear_api.remove_bike,
           # oauth apis
           "get_upload_signature": oauth_api.get_upload_signature,
           "check_upload_signature": oauth_api.check_upload_signature,
           # stats apis
           "get_stats": stats_api.get_stats,
           }


JQuery_Callbacks = ["jsoncallback","callback"]
Unwanted_Params = ["_"]

class APIRESTDispatcher(object):
    methods = METHODS

    def __init__(self, request, parameters=None):
        http_dict = {}
        if request.method == "GET":
            http_dict = request.GET
        elif request.method == "POST":
            http_dict = request.POST
            
        self.parameters = parameters or {}
        http_dict = remove_oauth_params(http_dict)
        self.parameters.update(http_dict)
        
        self.request = request
        self.jsoncallback = None

    def get_parameter(self, param_name):
        try:
            return self.parameters[param_name]
        except KeyError, e:
            raise Exception("Parameter %s not found"%param_name)

    def dispatch(self, request):
        method_name = self.parameters.pop("method")

        for param in Unwanted_Params:
            self.parameters.pop(param, None)

        for callback in JQuery_Callbacks:
            self.jsoncallback = self.parameters.get(callback, None)
            if self.jsoncallback:
                self.parameters.pop(callback)

        logging.info("REST - %s :"%(method_name))
        logging.info("    parameters: %s"%self.parameters.keys())

        method = self.get_method(method_name)

        if hasattr(method, "escape") and method.escape is False:
            pass  # do nothing
        else:
            self.parameters = escape_parameters(self.parameters)

        return method(request, **self.parameters)

    @classmethod
    def get_method_doc(cls, method_name):
        method = cls.get_method(method_name)
        return method.func_doc

    @classmethod
    def get_method(cls, method_name):
        if method_name not in APIRESTDispatcher.methods:
            raise Exception("method '%s' is not supported"%method_name)
        return APIRESTDispatcher.methods[method_name]

    @classmethod
    def get_dispatcher(cls, request, parameters=None):
        return cls(request, parameters)

        
def main():
    pass

if __name__ == '__main__':
    main()
